﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Odyssey.BouncyCastle.SMUtil
{
    using System;
    using System.Collections.Generic;
    using System.Text;

    public class HexUtil
    {
        private static Dictionary<char, byte> HEX_DIC = new Dictionary<char, byte>(0x10);
        private const string HEX_STRING = "0123456789ABCDEF";

        static HexUtil()
        {
            HEX_DIC.Add('0', 0);
            HEX_DIC.Add('1', 1);
            HEX_DIC.Add('2', 2);
            HEX_DIC.Add('3', 3);
            HEX_DIC.Add('4', 4);
            HEX_DIC.Add('5', 5);
            HEX_DIC.Add('6', 6);
            HEX_DIC.Add('7', 7);
            HEX_DIC.Add('8', 8);
            HEX_DIC.Add('9', 9);
            HEX_DIC.Add('A', 10);
            HEX_DIC.Add('B', 11);
            HEX_DIC.Add('C', 12);
            HEX_DIC.Add('D', 13);
            HEX_DIC.Add('E', 14);
            HEX_DIC.Add('F', 15);
        }
        public static byte[] FromHexString(string hexStr)
        {
            if (string.IsNullOrEmpty(hexStr))
            {
                return new byte[0];
            }

            if (hexStr.StartsWith("0x"))
            {
                hexStr = hexStr.Remove(0, 2);
            }

            var count = hexStr.Length;

            //if (count % 2 == 1)
            //{
            //    throw new ArgumentException("Invalid length of bytes:" + count);
            //}

            var byteCount = count / 2;
            var result = new byte[byteCount];
            for (int ii = 0; ii < byteCount; ++ii)
            {
                var tempBytes = Byte.Parse(hexStr.Substring(2 * ii, 2), System.Globalization.NumberStyles.HexNumber);
                result[ii] = tempBytes;
            }

            return result;
        }
        //public static byte[] FromHexString(string hexString)
        //{
        //    hexString = hexString.Replace(" ", "").ToUpper();
        //    if ((hexString.Length % 2) != 0)
        //    {
        //        hexString = "0" + hexString;
        //    }
        //    int num = hexString.Length / 2;
        //    byte[] buffer = new byte[num];
        //    try
        //    {
        //        for (int i = 0; i < num; i++)
        //        {
        //            buffer[i] = HEX_DIC[hexString[2 * i]] << 4;
        //            buffer[i] |= HEX_DIC[hexString[(2 * i) + 1]];
        //        }
        //    }
        //    catch (Exception exception)
        //    {
        //        throw new Exception("您输入的16进制串必须是由0-9,A-F组成（不区分大小写，自动忽略空格）", exception);
        //    }
        //    return buffer;
        //}

        public static string ToHexString(byte[] bytes)
        {
            int length = bytes.Length;
            StringBuilder builder = new StringBuilder(length * 2);
            for (int i = 0; i < length; i++)
            {
                builder.Append("0123456789ABCDEF"[(bytes[i] & 240) >> 4]);
                builder.Append("0123456789ABCDEF"[bytes[i] & 15]);
            }
            return builder.ToString();
        }

        public static string ToHexString(byte[] bytes, SpacePosition space)
        {
            return ToHexString(bytes, 0, space);
        }

        public static string ToHexString(byte[] bytes, int start, SpacePosition space)
        {
            int length = bytes.Length;
            StringBuilder builder = new StringBuilder((length - start) * 2);
            //int num2 = (length - start) % 4;
            int num3 = 0;
            for (int i = start; i < length; i++)
            {
                if (space != SpacePosition.None)
                {
                    //if (space == SpacePosition.Back)
                    //{
                    //    if ((num3 > 0) && ((num3 % 4) == num2))
                    //    {
                    //        builder.Append(' ');
                    //    }
                    //}
                    //else if ((space == SpacePosition.Front) && ((num3 > 0) && ((num3 % 4) == 0)))
                    //{
                    //    builder.Append(' ');
                    //}
                    num3++;
                }
                builder.Append("0123456789ABCDEF"[(bytes[i] & 240) >> 4]);
                builder.Append("0123456789ABCDEF"[bytes[i] & 15]);
            }
            return builder.ToString();
        }

        public static string ToHexString(byte[] bytes, SpacePosition space, int length)
        {
            return ToHexString(bytes, 0, space, length);
        }

        public static string ToHexString(byte[] bytes, int start, SpacePosition space, int length)
        {
            int num5;
            int num = bytes.Length;
            if (length <= 0)
            {
                length = num - start;
            }
            StringBuilder builder = new StringBuilder(length * 2);
            int num2 = length % 4;
            int num3 = 0;
            int num4 = length - (num - start);
            for (num5 = 0; num5 < num4; num5++)
            {
                if (space != SpacePosition.None)
                {
                    if (space == SpacePosition.Back)
                    {
                        if ((num3 > 0) && ((num3 % 4) == num2))
                        {
                            builder.Append(' ');
                        }
                    }
                    else if ((space == SpacePosition.Front) && ((num3 > 0) && ((num3 % 4) == 0)))
                    {
                        builder.Append(' ');
                    }
                    num3++;
                }
                builder.Append("00");
            }
            for (num5 = start; num5 < (start + length); num5++)
            {
                if (space != SpacePosition.None)
                {
                    if (space == SpacePosition.Back)
                    {
                        if ((num3 > 0) && ((num3 % 4) == num2))
                        {
                            builder.Append(' ');
                        }
                    }
                    else if ((space == SpacePosition.Front) && ((num3 > 0) && ((num3 % 4) == 0)))
                    {
                        builder.Append(' ');
                    }
                    num3++;
                }
                builder.Append("0123456789ABCDEF"[(bytes[num5] & 240) >> 4]);
                builder.Append("0123456789ABCDEF"[bytes[num5] & 15]);
            }
            return builder.ToString();
        }

        public static byte[] XOR(byte[] A, byte[] B)
        {
            if (A.Length != B.Length)
            {
                throw new Exception("进行异或的两组数据必须等长！");
            }
            byte[] buffer = new byte[A.Length];
            for (int i = 0; i < A.Length; i++)
            {
                buffer[i] = (byte)(A[i] ^ B[i]);
            }
            return buffer;
        }

        public enum SpacePosition
        {
            Front,
            Back,
            None
        }
    }
}

